#pragma once

#include "message.h"
#include "ProtoAdaptor.h"

namespace qb
{
	typedef unsigned long	DWORD;

	int safe_copy(char* szDestination, size_t isize, const char* szSource);

	class SSPROTOAPI CParserTool {
	public:
		static const char* GetString(const ProtoMap& msgmap, const char* name);
		static const char* GetString(const ProtoMessage& msg, const char* name);
		static const char* GetString(const qb::proto::VariantRecord* msg, const char* name);
		static const char* ToGBK(const char* utf8, int len);
		static bool MessageGetTime(const qb::proto::VariantRecord* msg, const std::string& name, time_t& t);

		static bool MessageGetTime(const ProtoMessage& msg, const std::string& name, time_t& t);
		static bool MessageGetInt64toTime(const ProtoMessage& msg, const std::string& name, time_t& t);
		static bool MessageGetDoubleToFloat(const ProtoMessage& msg, const std::string& name, float& fvalue);
		static bool MessageGetUint32ToDWORD(const ProtoMessage& msg, const std::string& name, DWORD& dwValue);
		static bool MessageGetUint64ToDWORD(const ProtoMessage& msg, const std::string& name, DWORD& dwValue);
		static bool MessageGetUint64ToDouble(const ProtoMessage& msg, const std::string& name, double& dwValue);
		static bool MessageGetInt64ToLong(const ProtoMessage& msg, const std::string& name, long& lValue);

		static bool MessageGetTime(const ProtoMap& msg, const std::string& name, time_t& t);
		static bool MessageGetInt64toTime(const ProtoMap& msg, const std::string& name, time_t& t);
		static bool MessageGetDoubleToFloat(const ProtoMap& msg, const std::string& name, float& fvalue);
		static bool MessageGetUint32ToDWORD(const ProtoMap& msg, const std::string& name, DWORD& dwValue);
		static bool MessageGetUint64ToDWORD(const ProtoMap& msg, const std::string& name, DWORD& dwValue);
		static bool MessageGetUint64ToDouble(const ProtoMap& msg, const std::string& name, double& dwValue);
		static bool MessageGetInt64ToLong(const ProtoMap& msg, const std::string& name, long& lValue);

		static std::string GetTypebyFuncID(int nFuncID);
		static int GetFuncIDbyType(const std::string& stype);

		static std::string UTF8ToGBK(const std::string& strUTF8);
		static void GetDoubleToString(const char* fieldName, std::string& dest, const ProtoMap& VMap);

	public:
		static bool IsStringEqual(const std::string& str, const char* s);
		static bool VariantRefString(const ProtoValue& vt, std::string& out);
		static void MapRefString(const ProtoMap& vmap, const char* name, std::string& out);
		static bool IsVerbosLogEnable();
		static bool IsCheckEnable();

	private:
		CParserTool() = delete;
		~CParserTool() = delete;
	};

	class DecodeMetric {
	public:
		DecodeMetric(double* ptime, const char* buf, int len, int funcid);
		~DecodeMetric();

	private:
		double* m_ptime;
	//	qb::base::HighResTime m_timer; //syy
		const char* m_buffer;
		int m_length;
		int	m_funcid;
	};
}

const uint8_t     SSTYPE_MIN = 0;
const uint8_t     SSTYPE_UNKNOWN = 0;
const uint8_t     SSTYPE_INT8 = 1;
const uint8_t     SSTYPE_UINT8 = 2;
const uint8_t     SSTYPE_INT16 = 3;
const uint8_t     SSTYPE_UINT16 = 4;
const uint8_t     SSTYPE_INT32 = 5;
const uint8_t     SSTYPE_UINT32 = 6;
const uint8_t     SSTYPE_INT64 = 7;
const uint8_t     SSTYPE_UINT64 = 8;
const uint8_t     SSTYPE_BOOL = 9;
const uint8_t     SSTYPE_STRING = 10;
const uint8_t     SSTYPE_FLOAT = 11;
const uint8_t     SSTYPE_DOUBLE = 12;
const uint8_t     SSTYPE_RAW = 13;
const uint8_t		SSTYPE_T32 = 14;		//等同于time_t，精度秒
const uint8_t		SSTYPE_T64 = 15;		//等同于time_t + 毫秒，精度毫秒
const uint8_t     SSTYPE_MAX = 15;

#define IFHEAD(key) if (CParserTool::IsStringEqual(vHeaders[cnt],key))

#define GETITEM_STRING(param)	\
	if (!*sFileBuffer)\
	{\
		++sFileBuffer;\
		FIELDCOPY(unit.param, sFileBuffer);\
		sFileBuffer = sFileBuffer + strlen(sFileBuffer) + 1;\
	}\
	else\
	{\
		++sFileBuffer;\
	}

#define GETITEM_STRING_NULL()	\
	if (!*sFileBuffer)\
			{\
		++sFileBuffer;\
		sFileBuffer = sFileBuffer + strlen(sFileBuffer) + 1;\
			}\
	else\
	{\
		++sFileBuffer;\
	}

#define GETITEM_STRING_UTF8(param)	\
	if (!*sFileBuffer)\
	{\
		++sFileBuffer;\
		const char* gbkstr = CParserTool::ToGBK(sFileBuffer, strlen(sFileBuffer));\
		FIELDCOPY(unit.param, gbkstr);\
		sFileBuffer = sFileBuffer + strlen(sFileBuffer) + 1;\
	}\
	else\
	{\
		++sFileBuffer;\
	}

#define GETITEM_STRING_UTF8_EX(param)\
	if (!*sFileBuffer)\
	{\
		++sFileBuffer;\
		const char* gbkstr = CParserTool::ToGBK(sFileBuffer, strlen(sFileBuffer));\
		unit.param = gbkstr;\
		sFileBuffer = sFileBuffer + strlen(sFileBuffer) + 1;\
	}\
	else\
	{\
		++sFileBuffer;\
	}

#define GETITEM_STDSTRING_UTF8(param)	\
	if (!*sFileBuffer)\
			{\
		++sFileBuffer;\
		const char* gbkstr = CParserTool::ToGBK(sFileBuffer, strlen(sFileBuffer));\
		FIELDCOPY(param, gbkstr);\
		sFileBuffer = sFileBuffer + strlen(sFileBuffer) + 1;\
			}\
				else\
	{\
		++sFileBuffer;\
	}

#ifndef _MSC_VER
#ifndef MEMCPYS
        static void memcpy_s(void *det, size_t detSize, const void * src, size_t srcSize)
        {
            if (srcSize > detSize || src == NULL || det == NULL)
            {
                return;
            }
            else
            {
                memcpy(det, src, srcSize);
            }
        }
#define MEMCPYS
#endif
#endif

#define GETITEM_BUFFER(type, param)	\
	if (!*sFileBuffer)\
	{\
		++sFileBuffer;\
		memcpy_s(&unit.param, sizeof(type), sFileBuffer, sizeof(type));\
		sFileBuffer += sizeof(type);\
	}\
	else\
	{\
		++sFileBuffer;\
	}

#define ELSESKIP \
	else\
	{/*skip buffer because cannot match header name in vHeaders*/\
		if (*sFileBuffer)\
			++sFileBuffer; \
		else\
		{\
			--sFileBuffer; \
			if (*sFileBuffer == SSTYPE_STRING)\
			{\
				sFileBuffer += 2; \
				while (*sFileBuffer++); \
			}\
			else if (*sFileBuffer == SSTYPE_FLOAT)\
			{\
				sFileBuffer += 6; \
			}\
			else if (*sFileBuffer == SSTYPE_DOUBLE)\
			{\
				sFileBuffer += 10; \
			}\
			else if (*sFileBuffer == SSTYPE_INT32)\
			{\
				sFileBuffer += 6; \
			}\
		}\
	}

